home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / pine / imap-3.0 / ANSI / c-client / os_t20.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-12-03  |  11.4 KB  |  422 lines

  1. /*
  2.  * Program:    Operating-system dependent routines -- TOPS-20 version
  3.  *
  4.  * Author:    Mark Crispin
  5.  *        6158 Lariat Loop NE
  6.  *        Bainbridge Island, WA  98110-2098
  7.  *        Internet: MRC@Panda.COM
  8.  *
  9.  * Date:    1 August 1988
  10.  * Last Edited:    3 December 1992
  11.  *
  12.  * Copyright 1992 by Mark Crispin
  13.  *
  14.  *  Permission to use, copy, modify, and distribute this software and its
  15.  * documentation for any purpose and without fee is hereby granted, provided
  16.  * that the above copyright notices appear in all copies and that both the
  17.  * above copyright notices and this permission notice appear in supporting
  18.  * documentation, and that the name of Mark Crispin not be used in advertising
  19.  * or publicity pertaining to distribution of the software without specific,
  20.  * written prior permission.  This software is made available "as is", and
  21.  * MARK CRISPIN DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD TO
  22.  * THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED WARRANTIES OF
  23.  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN NO EVENT SHALL
  24.  * MARK CRISPIN BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES
  25.  * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  26.  * WHETHER IN AN ACTION OF CONTRACT, TORT (INCLUDING NEGLIGENCE) OR STRICT
  27.  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
  28.  * THIS SOFTWARE.
  29.  *
  30.  */
  31.  
  32.  
  33. /* Dedication:
  34.  * This file is dedicated with affection to the TOPS-20 operating system, which
  35.  * set standards for user and programmer friendliness that have still not been
  36.  * equaled by more `modern' operating systems.
  37.  * Wasureru mon ka!!!!
  38.  */
  39.  
  40. /* TCP input buffer */
  41.  
  42. #define BUFLEN 8192
  43.  
  44. /* TCP I/O stream (must be before osdep.h is included) */
  45.  
  46. #define TCPSTREAM struct tcp_stream
  47. TCPSTREAM {
  48.   char *host;            /* host name */
  49.   char *localhost;        /* local host name */
  50.   int jfn;            /* jfn for connection */
  51.   char ibuf[BUFLEN];        /* input buffer */
  52. };
  53.  
  54.  
  55. #include "mail.h"
  56. #include <jsys.h>
  57. #include <time.h>
  58. #include "osdep.h"
  59. #include <sys/time.h>
  60. #include "misc.h"
  61.  
  62. /* Write current time in RFC 822 format
  63.  * Accepts: destination string
  64.  */
  65.  
  66. char *days[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
  67.  
  68. void rfc822_date (char *date)
  69. {
  70.   int zone;
  71.   char *zonename;
  72.   struct tm *t;
  73.   struct timeval tv;
  74.   struct timezone tz;
  75.   gettimeofday (&tv,&tz);    /* get time and timezone poop */
  76.   t = localtime (&tv.tv_sec);    /* convert to individual items */
  77.   zone = -tz.tz_minuteswest;    /* TOPS-20 doesn't have tm_gmtoff or tm_zone */
  78.   zonename = timezone (tz.tz_minuteswest,t->tm_isdst);
  79.                 /* and output it */
  80.   sprintf (date,"%s, %d %s %d %02d:%02d:%02d %+03d%02d (%s)",
  81.        days[t->tm_wday],t->tm_mday,months[t->tm_mon],t->tm_year+1900,
  82.        t->tm_hour,t->tm_min,t->tm_sec,
  83.        (t->tm_isdst ? 1 : 0) + zone/60,abs (zone) % 60,zonename);
  84. }
  85.  
  86. /* Get a block of free storage
  87.  * Accepts: size of desired block
  88.  * Returns: free storage block
  89.  */
  90.  
  91. void *fs_get (size_t size)
  92. {
  93.   void *block = malloc (size);
  94.   if (!block) fatal ("Out of free storage");
  95.   return (block);
  96. }
  97.  
  98.  
  99. /* Resize a block of free storage
  100.  * Accepts: ** pointer to current block
  101.  *        new size
  102.  */
  103.  
  104. void fs_resize (void **block,size_t size)
  105. {
  106.   if (!(*block = realloc (*block,size))) fatal ("Can't resize free storage");
  107. }
  108.  
  109.  
  110. /* Return a block of free storage
  111.  * Accepts: ** pointer to free storage block
  112.  */
  113.  
  114. void fs_give (void **block)
  115. {
  116.   free (*block);
  117.   *block = NIL;
  118. }
  119.  
  120.  
  121. /* Report a fatal error
  122.  * Accepts: string to output
  123.  */
  124.  
  125. void fatal (char *string)
  126. {
  127.   mm_fatal (string);        /* pass up the string */
  128.   abort ();            /* die horribly */
  129. }
  130.  
  131. /* Copy string with CRLF newlines
  132.  * Accepts: destination string
  133.  *        pointer to size of destination string
  134.  *        source string
  135.  *        length of source string
  136.  */
  137.  
  138. char *strcrlfcpy (char **dst,unsigned long *dstl,char *src,unsigned long srcl)
  139. {
  140.   if (srcl > *dstl) {        /* make sure enough space for text */
  141.     fs_give ((void **) dst);    /* fs_resize does an unnecessary copy */
  142.     *dst = (char *) fs_get ((*dstl = srcl) + 1);
  143.   }
  144.                 /* copy strings */
  145.   if (srcl) memcpy (*dst,src,srcl);
  146.   *(*dst + srcl) = '\0';    /* tie off destination */
  147.   return *dst;            /* return destination */
  148. }
  149.  
  150.  
  151. /* Length of string after strcrlfcpy applied
  152.  * Accepts: source string
  153.  *        length of source string
  154.  */
  155.  
  156. unsigned long strcrlflen (STRING *s)
  157. {
  158.   return SIZE (s);        /* this is easy on TOPS-20 */
  159. }
  160.  
  161. /* Server log in
  162.  * Accepts: user name string
  163.  *        password string
  164.  *        optional place to return home directory
  165.  * Returns: T if password validated, NIL otherwise
  166.  */
  167.  
  168. long server_login (char *user,char *pass,char **home,int argc,char *argv[])
  169. {
  170.   int uid;
  171.   int argblk[5];
  172.   char tmp[MAILTMPLEN];
  173.   argblk[1] = RC_EMO;        /* require exact match */
  174.   argblk[2] = (int) (user-1);    /* user name */
  175.   argblk[3] = 0;        /* no stepping */
  176.   if (!jsys (RCUSR,argblk)) return NIL;
  177.   uid = argblk[1] = argblk[3];    /* user number */
  178.   argblk[2] = (int) (pass-1);    /* password */
  179.   argblk[3] = 0;        /* no special account */
  180.   if (!jsys (LOGIN,argblk)) return NIL;
  181.   if (home) {            /* wants home directory? */
  182.     argblk[1] = 0;        /* no special flags */
  183.     argblk[2] = uid;        /* user number */
  184.     argblk[3] = 0;        /* no stepping */
  185.     jsys (RCDIR,argblk);    /* get directory number */
  186.     argblk[1] = (int) (tmp-1);    /* destination */
  187.     argblk[2] = argblk[3];    /* directory number */
  188.     jsys (DIRST,argblk);    /* get home directory string */
  189.     *home = cpystr (tmp);    /* copy home directory */
  190.   }
  191.   return T;
  192. }
  193.  
  194. /* TCP/IP open
  195.  * Accepts: host name
  196.  *        contact port number
  197.  * Returns: TCP stream if success else NIL
  198.  */
  199.  
  200. TCPSTREAM *tcp_open (char *host,int port)
  201. {
  202.   char tmp[MAILTMPLEN];
  203.   TCPSTREAM *stream = NIL;
  204.   int argblk[5];
  205.   int jfn;
  206.   char file[MAILTMPLEN];
  207.   argblk[1] = monsym (".GTDPN");/* get IP address and primary name */
  208.   argblk[2] = (int) (host-1);    /* pointer to host */
  209.   argblk[4] = (int) (tmp-1);
  210.   if (!jsys (GTDOM,argblk)) {    /* do it the domain way */
  211.     argblk[1] = _GTHSN;        /* failed, convert string to number */
  212.     if (!jsys (GTHST,argblk)) {    /* and do it by host table */
  213.       sprintf (tmp,"No such host as %s",host);
  214.       mm_log (tmp,ERROR);
  215.       return NIL;
  216.     }
  217.     argblk[1] = _GTHNS;        /* convert number to string */
  218.     argblk[2] = (int) (tmp-1);
  219.                 /* get the official name */
  220.     if (!jsys (GTHST,argblk)) strcpy (tmp,host);
  221.   }
  222.   sprintf (file,"TCP:.%o-%d;PERSIST:30;CONNECTION:ACTIVE",argblk[3],port);
  223.   argblk[1] = GJ_SHT;        /* short form GTJFN% */
  224.   argblk[2] = (int) (file-1);    /* pointer to file name */
  225.                 /* get JFN for TCP: file */
  226.   if (!jsys (GTJFN,argblk)) fatal ("Unable to create TCP JFN");
  227.   jfn = argblk[1];        /* note JFN for later */
  228.                 /* want 8-bit bidirectional I/O */
  229.   argblk[2] = OF_RD|OF_WR|(FLD (8,monsym("OF%BSZ")));
  230.   if (!jsys (OPENF,argblk)) {
  231.     sprintf (file,"Can't connect to %s,%d server",tmp,port);
  232.     mm_log (file,ERROR);
  233.     return NIL;
  234.   }
  235.                 /* create TCP/IP stream */
  236.   stream = (TCPSTREAM *) fs_get (sizeof (TCPSTREAM));
  237.                 /* copy official host name */
  238.   stream->host = cpystr (tmp);
  239.   argblk[1] = _GTHNS;        /* convert number to string */
  240.   argblk[2] = (int) (tmp-1);
  241.   argblk[3] = -1;        /* want local host */
  242.   if ((!jsys (GTDOM,argblk)) && !jsys (GTHST,argblk)) strcpy (tmp,"LOCAL");
  243.   stream->localhost = cpystr (tmp);
  244.   stream->jfn = jfn;        /* init JFN */
  245.   return stream;
  246. }
  247.  
  248. /* TCP/IP authenticated open
  249.  * Accepts: host name
  250.  *        service name
  251.  * Returns: TCP/IP stream if success else NIL
  252.  */
  253.  
  254. TCPSTREAM *tcp_aopen (char *host,char *service)
  255. {
  256.   return NIL;
  257. }
  258.  
  259. /* TCP/IP receive line
  260.  * Accepts: TCP/IP stream
  261.  * Returns: text line string or NIL if failure
  262.  */
  263.  
  264. char *tcp_getline (TCPSTREAM *stream)
  265. {
  266.   int argblk[5];
  267.   int n,m;
  268.   char *ret,*stp,*st;
  269.   argblk[1] = stream->jfn;    /* read from TCP */
  270.                 /* pointer to buffer */
  271.   argblk[2] = (int) (stream->ibuf-1);
  272.   argblk[3] = BUFLEN;        /* max number of bytes to read */
  273.   argblk[4] = '\012';        /* terminate on LF */
  274.   if (!jsys (SIN,argblk)) return NIL;
  275.   n = BUFLEN - argblk[3];    /* number of bytes read */
  276.                 /* got a complete line? */
  277.   if ((stream->ibuf[n - 2] == '\015') && (stream->ibuf[n - 1] == '\012')) {
  278.     memcpy ((ret = (char *) fs_get (n)),stream->ibuf,n - 2);
  279.     ret[n - 2] = '\0';    /* tie off string with null */
  280.     return ret;
  281.   }
  282.                 /* copy partial string */
  283.   memcpy ((stp = ret = (char *) fs_get (n)),stream->ibuf,n);
  284.                 /* special case of newline broken by buffer */
  285.   if ((stream->ibuf[n - 1] == '\015') && jsys (BIN,argblk) &&
  286.       (argblk[2] == '\012')) {    /* was it? */
  287.     ret[n - 1] = '\0';        /* tie off string with null */
  288.   }
  289.                 /* recurse to get remainder */
  290.   else if (jsys (BKJFN,argblk) && (st = tcp_getline (stream))) {
  291.     ret = (char *) fs_get (n + 1 + (m = strlen (st)));
  292.     memcpy (ret,stp,n);        /* copy first part */
  293.     memcpy (ret + n,st,m);    /* and second part */
  294.     fs_give ((void **) &stp);    /* flush first part */
  295.     fs_give ((void **) &st);    /* flush second part */
  296.     ret[n + m] = '\0';        /* tie off string with null */
  297.   }
  298.   return ret;
  299. }
  300.  
  301. /* TCP/IP receive buffer
  302.  * Accepts: TCP/IP stream
  303.  *        size in bytes
  304.  *        buffer to read into
  305.  * Returns: T if success, NIL otherwise
  306.  */
  307.  
  308. long tcp_getbuffer (TCPSTREAM *stream,unsigned long size,char *buffer)
  309. {
  310.   int argblk[5];
  311.   argblk[1] = stream->jfn;    /* read from TCP */
  312.   argblk[2] = (int) (buffer-1);    /* pointer to buffer */
  313.   argblk[3] = -size;        /* number of bytes to read */
  314.   if (!jsys (SIN,argblk)) return NIL;
  315.   buffer[size] = '\0';        /* tie off text */
  316.   return T;
  317. }
  318.  
  319.  
  320. /* TCP/IP send string as record
  321.  * Accepts: TCP/IP stream
  322.  *        string pointer
  323.  * Returns: T if success else NIL
  324.  */
  325.  
  326. long tcp_soutr (TCPSTREAM *stream,char *string)
  327. {
  328.   int argblk[5];
  329.   argblk[1] = stream->jfn;    /* write to TCP */
  330.   argblk[2] = (int) (string-1);    /* pointer to buffer */
  331.   argblk[3] = 0;        /* write until NUL */
  332.   if (!jsys (SOUTR,argblk)) return NIL;
  333.   return T;
  334. }
  335.  
  336.  
  337. /* TCP/IP send string
  338.  * Accepts: TCP/IP stream
  339.  *        string pointer
  340.  *        byte count
  341.  * Returns: T if success else NIL
  342.  */
  343.  
  344. long tcp_sout (TCPSTREAM *stream,char *string,unsigned long size)
  345. {
  346.   int argblk[5];
  347.   argblk[1] = stream->jfn;    /* write to TCP */
  348.   argblk[2] = (int) (string-1);    /* pointer to buffer */
  349.   argblk[3] = -size;        /* write this many bytes */
  350.   if (!jsys (SOUTR,argblk)) return NIL;
  351.   return T;
  352. }
  353.  
  354. /* TCP/IP close
  355.  * Accepts: TCP/IP stream
  356.  */
  357.  
  358. void tcp_close (TCPSTREAM *stream)
  359. {
  360.   int argblk[5];
  361.   argblk[1] = stream->jfn;    /* close TCP */
  362.   jsys (CLOSF,argblk);
  363.                 /* flush host names */
  364.   fs_give ((void **) &stream->host);
  365.   fs_give ((void **) &stream->localhost);
  366.   fs_give ((void **) &stream);    /* flush the stream */
  367. }
  368.  
  369.  
  370. /* TCP/IP return host for this stream
  371.  * Accepts: TCP/IP stream
  372.  * Returns: host name for this stream
  373.  */
  374.  
  375. char *tcp_host (TCPSTREAM *stream)
  376. {
  377.   return stream->host;        /* return host name */
  378. }
  379.  
  380.  
  381. /* TCP/IP return local host for this stream
  382.  * Accepts: TCP/IP stream
  383.  * Returns: local host name for this stream
  384.  */
  385.  
  386. char *tcp_localhost (TCPSTREAM *stream)
  387. {
  388.   return stream->localhost;    /* return local host name */
  389. }
  390.  
  391. /* Subscribe to mailbox
  392.  * Accepts: mailbox name
  393.  * Returns: T on success, NIL on failure
  394.  */
  395.  
  396. long sm_subscribe (char *mailbox)
  397. {
  398.   return NIL;            /* needs to be written */
  399. }
  400.  
  401.  
  402. /* Unsubscribe from mailbox
  403.  * Accepts: mailbox name
  404.  * Returns: T on success, NIL on failure
  405.  */
  406.  
  407. long sm_unsubscribe (char *mailbox)
  408. {
  409.   return NIL;            /* needs to be written */
  410. }
  411.  
  412.  
  413. /* Read subscription database
  414.  * Accepts: pointer to subscription database handle (handle NIL if first time)
  415.  * Returns: character string for subscription database or NIL if done
  416.  */
  417.  
  418. char *sm_read (void **sdb)
  419. {
  420.   return NIL;
  421. }
  422.